import logging
logging.basicConfig(level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[logging.StreamHandler()])
from PySide6.QtCore import Qt, QUrl, QRect, QPropertyAnimation, QEasingCurve, QByteArray, Qt as QtCore
from PySide6.QtGui import QPixmap, QColor, QBrush,QStandardItemModel, QStandardItem,QAction

from pathlib import Path
import sys
from PySide6.QtWidgets import (QMainWindow, QApplication, QFileDialog, QPushButton,QAbstractItemView,QVBoxLayout,
    QMessageBox, QLabel, QListView, QTreeWidget, QTreeWidgetItem, QListWidget, QMenu)
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from ui_mainwindow import Ui_MainWindow
from mutagen._file import File
from mutagen.flac import FLAC
from mutagen.mp3 import MP3
import time
import os
import typing
import json
import playlist_handlers,show_lyrics
from playlist_handlers import handle_playlist_double_click
from show_lyrics import LyricsManager
from license_dialog import LicenseDialog
from about_yetu_player import AboutYeTuPlayer


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        logging.debug('MainWindow初始化开始')
        # 添加路径处理代码，注意该代码需要放在所有其他代码之前
        if getattr(sys, 'frozen', False):
            application_path = sys._MEIPASS
        else:
            application_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(application_path)

        self.setupUi(self)
        self.setWindowTitle('野兔音乐播放器_V0.31beta')
        self.setWindowIcon(QPixmap('icons/app_icon.ico'))
        self.setFixedSize(self.width(), self.height())

        # 初始化主题管理器
        from theme_manager import ThemeManager
        self.theme_manager = ThemeManager()
        self.theme_manager.load_theme('default')

        # 初始化媒体组件
        self.media_player = QMediaPlayer()  # 初始化媒体播放器
        self.audio_output = QAudioOutput()  # 初始化音频输出

        self.media_player.errorOccurred.connect(self.handle_media_error) # 连接错误信号
        self.media_player.setAudioOutput(self.audio_output) # 设置音频输出


        # 初始化右键菜单
        self.context_menu = QMenu(self)
        self.delete_action = QAction('删除选中项', self)
        self.export_action = QAction('导出选中项', self)
        self.context_menu.addAction(self.delete_action)
        self.context_menu.addAction(self.export_action)
        self.delete_action.triggered.connect(self.delete_selected_items)
        self.export_action.triggered.connect(self.export_selected_items)
        
        # 初始化歌词管理器
        self.lyrics_list = self.findChild(QListWidget, "lyrics_list")
        if not self.lyrics_list:
            logging.error("未能找到歌词列表控件lyrics_list")
            self.lyrics_list = QListWidget()
        self.lyrics_manager = LyricsManager(self.lyrics_list)
        # 初始化歌词数据字典
        #self.lyrics_data = {} #这行不是必须


        # 连接音量控制信号
        self.volume_control.valueChanged.connect(lambda v: self.audio_output.setVolume(v/100))
        # 连接播放状态信号
        self.media_player.mediaStatusChanged.connect(self.handle_media_status)
        # 连接播放进度信号
        self.media_player.positionChanged.connect(self.lyrics_manager.update_lyrics)
        self.media_player.positionChanged.connect(self.update_progress)
        self.media_player.durationChanged.connect(self.update_duration)  # 新增信号连接
        self.progress_slider.sliderMoved.connect(self.seek_position)
        # 创建垂直布局
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        # 初始化表格模型
        # 初始化音乐信息列表模型
        self.music_info_model = QStandardItemModel()
        
        # 初始化播放列表
        self.playlist = self.findChild(QTreeWidget, "play_list")
        if self.playlist is not None:
            self.playlist.setHeaderLabels(['序号','歌曲名称', '演唱者', '专辑名称', '时长', '比特率', '格式'])
            # 设置多选模式
            self.playlist.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
            # 初始化当前选中项
            if self.playlist.topLevelItemCount() > 0:
                self.playlist.setCurrentItem(self.playlist.topLevelItem(0))
        else:
            logging.error("未能找到播放列表控件play_list")
            self.playlist = QTreeWidget()  # 创建备用播放列表控件
            self.playlist.setHeaderLabels(['序号','歌曲名称', '演唱者', '专辑名称', '时长', '比特率', '格式'])
            self.verticalLayout.addWidget(self.playlist)
        # 安全设置列对齐方式
        if self.playlist:
            # 确保存在表头项
            if not self.playlist.headerItem():
                self.playlist.setHeaderLabels(['序号','歌曲名称', '演唱者', '专辑名称', '时长', '比特率', '格式'])
            
            for col in range(7):
                header = self.playlist.headerItem()
                if col in [0, 6]:
                    header.setTextAlignment(col, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap)
                elif col in [4, 5]:
                    header.setTextAlignment(col, Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
                # 统一设置列宽
        columns = [
            (0, 50),    # 序号
            (1, 120),   # 歌曲名称
            (2, 80),    # 演唱者
            (3, 120),   # 专辑名称
            (4, 50),    # 时长
            (5, 80),    # 比特率
            (6, 60)     # 格式
        ]
        if self.playlist:
            for col, width in columns:
                self.playlist.setColumnWidth(col, width)
        else:
            logging.error("播放列表控件未找到，无法设置列宽")
        #        self.playlist.resizeColumnToContents(1)  # 自动宽度的语法
        # 连接双击信号
        if self.playlist:
            self.playlist.doubleClicked.connect(lambda: handle_playlist_double_click(
                self.playlist.currentItem(),
                self,
                self.media_player,
                self.lyrics_list,
                self.music_info,
                self.artist_name,
                self.album_name,
                self.bit_rate,
                self.audio_format,
                self.cover_label
            ))
        # 启用自定义上下文菜单
        self.playlist.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.playlist.customContextMenuRequested.connect(self.show_context_menu)
        # 初始化当前选中项
        self.playlist.setCurrentItem(self.playlist.topLevelItem(0))

        # 初始化封面缓存
        self.default_cover = QPixmap("icons/default_cover.png")
        
        # 初始化主题管理器
        from theme_manager import ThemeManager
        self.theme_manager = ThemeManager()
        
        # 连接主题切换动作
        self.dark_theme = self.findChild(QAction, "dark_theme")
        self.light_theme = self.findChild(QAction, "light_theme")
        self.default_theme = self.findChild(QAction, "default_theme")
        self.dark_theme.triggered.connect(lambda: self.theme_manager.load_theme("dark"))
        self.light_theme.triggered.connect(lambda: self.theme_manager.load_theme("light"))
        self.default_theme.triggered.connect(lambda: self.theme_manager.load_theme("default"))

        # 初始化播放控制状态
        self.is_playing = False
        self.current_file = None
        self.cycle_mode = 0  # 初始化播放模式
        
        # 合并音量控制信号
        self.volume_control.setValue(50)
        self.volume_control.valueChanged.emit(50)  # 手动触发信号同步
        self.volume_control.valueChanged.connect(lambda v: (
            self.audio_output.setVolume(v / 100),
            self.update_volume_display(v)
        ))
        self.volume_number.display(50)  # 初始化显示数值
        
        # 连接按钮信号
        self.actionImport_audio.triggered.connect(self.import_audio)
        self.actionImport_audio_folder.triggered.connect(self.import_audio_folder)
        self.actionImport_playlist.triggered.connect(self.import_playlist)
        self.qt_license.triggered.connect(self.show_license)
        self.about_yetu_player.triggered.connect(self.show_about_yetu_player)

        # 初始化所有控制按钮
        self.play_button = self.findChild(QPushButton, "play_button")
        self.stop_button = self.findChild(QPushButton, "stop_button")
        self.next_button = self.findChild(QPushButton, "nex_button")
        self.prev_button = self.findChild(QPushButton, "pre_button")
        self.cycle_button = self.findChild(QPushButton, "cycle_button")
        
        # 连接循环模式按钮点击事件
        if self.cycle_button:
            self.cycle_button.clicked.connect(self.toggle_cycle)
        # 安全连接播放控制按钮
        if self.play_button:
            self.play_button.clicked.connect(self.play)
        if self.stop_button:
            self.stop_button.clicked.connect(self.stop)
        if self.next_button:
            self.next_button.clicked.connect(self.next_song)
        if self.prev_button:
            self.prev_button.clicked.connect(self.previous_song)

        # 在初始化完成后加载播放列表
        self.load_playlist()

        #可以关闭系统title栏的用法，待研究
        #self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)



    def show_license(self):
        dlg = LicenseDialog(self)
        dlg.exec()

    def show_about_yetu_player(self):
        dlg = AboutYeTuPlayer(self)
        dlg.exec()

    def import_audio_folder(self):
        folder_path = QFileDialog.getExistingDirectory(self, '选择音频文件夹')
        if folder_path:
            import os
            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    if file.lower().endswith(('.mp3', '.flac')):
                        self._add_to_playlist(os.path.join(root, file))

    def import_audio(self):
        file_paths, _ = QFileDialog.getOpenFileNames(self, '选择音频文件', '', '音频文件 (*.mp3 *.flac)')
        for path in file_paths:
            self._add_to_playlist(path)

    def import_playlist(self):
        path, _ = QFileDialog.getOpenFileName(self, '导入播放列表', '', 'M3U Files (*.m3u)')
        if path:
            try:
                base_dir = os.path.dirname(path)
                with open(path, 'r', encoding='utf-8') as f:
                    for line in f:
                        line = line.strip()
                        if line and not line.startswith('#'):
                            # 处理相对路径
                            if not os.path.isabs(line):
                                file_path = os.path.normpath(os.path.join(base_dir, line))
                            else:
                                file_path = os.path.normpath(line)
                            
                            if os.path.isfile(file_path):
                                self._add_to_playlist(file_path)
                            else:
                                QMessageBox.warning(self, '无效文件', f'文件不存在: {file_path}')
                self.save_playlist()
            except Exception as e:
                QMessageBox.critical(self, '导入错误', f'播放列表导入失败:\n{str(e)}')

    def _add_to_playlist(self, file_path):
        # 重复文件检查
        normalized_path = os.path.normcase(os.path.abspath(file_path))
        for i in range(self.playlist.topLevelItemCount()):
            item = self.playlist.topLevelItem(i)
            existing_path = os.path.normcase(os.path.abspath(item.data(6, Qt.ItemDataRole.UserRole)))
            if existing_path == normalized_path:
                # QMessageBox.information(self, "重复文件", f"文件已存在于播放列表:\n{os.path.basename(file_path)}")
                return
        try:
            audio = File(file_path)          
            # 分离元数据获取方法
            def _get_mp3_tag(tags, *keys):
                for key in keys:
                    try:
                        # 支持多种专辑标签格式
                        value = tags.get(key)
                        if value:
                            if key in ['TALB', 'TAL']:  # 处理ID3v2标签
                                return str(value)
                            elif key in ['WM/AlbumTitle', 'Album']:  # 处理WMP标签
                                return str(value) if not isinstance(value, list) else value[0]
                            return value.text[0] if value.text else '未知'
                    except (KeyError, AttributeError, IndexError, TypeError) as e:
                        logging.debug(f'解析标签{key}时出错: {str(e)}')
                        continue
                return '未知'

            def _get_flac_tag(tags, *keys):
                for key in keys:
                    try:
                        return tags[key][0] if tags[key] else '未知'
                    except KeyError:
                        continue
                return '未知'

            # 获取格式特定元数据
            if isinstance(audio, MP3):
                audio = typing.cast(MP3, audio)
                if audio is not None and audio.info is not None:
                    info = audio.info
                    tags = audio.tags if (audio is not None and audio.tags) else {}
                    title = _get_mp3_tag(tags, 'TIT2', 'TIT1')
                    artist = _get_mp3_tag(tags, 'TPE1', 'TPE2')
                    album = _get_mp3_tag(tags, 'TALB', 'TAL')
                    bitrate = f'{round(info.bitrate/1000)} kbps'
                    file_format = 'MP3'
                   
                    # 新增封面数据提取逻辑
                    cover_data = None
                    try:
                        apics = tags.getall('APIC')
                        if apics:
                            # 优先查找类型3的专辑封面
                            cover_apic = next((apic for apic in apics if getattr(apic, 'type', 0) == 3), None)
                            if not cover_apic:
                                cover_apic = apics[0]  # 取第一个可用封面
                            cover_data = cover_apic.data
                    except Exception as e:
                        logging.warning(f'封面解析异常: {str(e)}')
            elif isinstance(audio, FLAC):
                audio = typing.cast(FLAC, audio)
                if audio is not None:
                    info = audio.info
                    tags = audio.tags if (audio is not None and audio.tags) else {}
                    title = _get_flac_tag(tags, 'TITLE', 'title')
                    artist = _get_flac_tag(tags, 'ARTIST', 'artist')
                    album = _get_flac_tag(tags, 'ALBUM', 'album')
                    file_size = Path(file_path).stat().st_size
                    duration = audio.info.length
                    bitrate = f'{int((file_size * 8) / max(duration, 1))} Kbps' if duration > 0 else '未知'
                    file_format = 'FLAC'
                
                # 获取FLAC封面
                cover_data = next((pic.data for pic in audio.pictures if pic.type == 3), None) if audio.pictures else None

            # 处理时长
            duration = round(audio.info.length)
            minutes = duration // 60
            seconds = duration % 60
            duration_str = f"{minutes}:{seconds:02d}"
            
            # 处理比特率
            if isinstance(audio, FLAC):
                file_size = Path(file_path).stat().st_size
                bitrate = int((file_size * 8) / (duration if duration > 0 else 1) / 1000)
                bitrate_str = f"{bitrate} kbps"
            else:
                bitrate = getattr(audio.info, 'bitrate', 0)
                bitrate_str = f"{round(bitrate)} kbps" if bitrate > 0 else "未知"
            if isinstance(audio, MP3):
                bitrate_rounded = round(bitrate / 1000)
                bitrate_str = f"{bitrate_rounded} kbps" if bitrate > 0 else "未知"
            else:
                bitrate_str = f"{int(bitrate)} kbps" if bitrate > 0 else "未知"
            
            # 获取文件格式
            file_format = 'MP3' if file_path.lower().endswith('.mp3') else 'FLAC'
                      
            # 创建表格行数据
            item = QTreeWidgetItem([
                str(self.playlist.topLevelItemCount() + 1),
                title,
                artist,
                album,
                duration_str,
                bitrate_str,
                file_format
            ])
            # 设置序号列和格式列居中
            item.setTextAlignment(0, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap) # 序号列
            item.setTextAlignment(4, Qt.AlignmentFlag.AlignRight) # 时长列
            item.setTextAlignment(5, Qt.AlignmentFlag.AlignRight) # 比特率列
            item.setTextAlignment(6, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextWordWrap) # 格式列  
                 
            # 将文件路径存储在最后一列（格式列）的UserRole
            item.setData(6, Qt.ItemDataRole.UserRole, file_path)
            
            meta = {
                'title': title,
                'artist': artist,
                'album': album,
                'bitrate': bitrate_str,
                'audioformat': file_format,
                'duration': duration_str,
                'cover_data': cover_data
            }
            # 在指定列设置数据（格式列第6列）
            item.setData(6, Qt.ItemDataRole.UserRole + 1, meta)
            
           # item.setText(5, meta['bitrate'])
            self.playlist.addTopLevelItem(item)

            # 歌词解析改为播放时处理
            meta['lyrics'] = ''
            
            # 自动同步模型更新
            self.music_info_model.layoutChanged.emit()

        except Exception as e:
            logging.error(f"解析文件失败: {str(e)} - 文件路径: {file_path}")
            # 在UI显示错误提示
            QMessageBox.warning(self, "文件加载失败", 
                f"无法加载文件:\n{Path(file_path).name}\n\n错误详情: {str(e)}",
                QMessageBox.StandardButton.Ok)

    def update_volume_display(self, value):
        self.volume_number.display(value)

    def handle_media_error(self, error, error_string):
        QMessageBox.warning(self, "播放错误", f"媒体播放错误({error}): {error_string}")

    def play(self):
        if self.media_player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
            self.media_player.pause()
            self.play_button.setText("播放")
        else:
            self.media_player.play()
            self.play_button.setText("暂停")

    def stop(self):
        self.media_player.stop()
        self.play_button.setText("播放")
        self.progress_slider.setValue(0)
        self.time_label.setText("00:00 / 00:00")
        # 停止时清空所有显示信息
        self.music_info.setTitle('')
        self.artist_name.setText('')
        self.album_name.setText('')
        self.bit_rate.setText('')
        self.audio_format.setText('')
        self.lyrics_list.clear()

    def next_song(self):
        self.music_info.setTitle('')
        self.artist_name.setText('')
        self.album_name.setText('')
        self.bit_rate.setText('')
        self.audio_format.setText('')
        self.lyrics_list.clear()
        self.current_cover = None
      
        if self.cycle_mode == 1: #随机模式下的动作
            self.play_random_song()
            return
        current_item = self.playlist.currentItem()  
        if self.cycle_mode in (0, 2):  #顺序播放和单曲播放下的动作
            row = self.playlist.indexOfTopLevelItem(current_item) + 1
            if row < self.playlist.topLevelItemCount():
                next_item = self.playlist.topLevelItem(row)
                self.playlist.setCurrentItem(next_item)
                
            if row == self.playlist.topLevelItemCount():
                first_item = self.playlist.topLevelItem(0)
                self.playlist.setCurrentItem(first_item)
            current_item = self.playlist.currentItem()  
        #self.media_player.play()  # 继续播放当前歌曲
            playlist_handlers.handle_playlist_double_click(self.playlist.currentItem(), self, 
                self.media_player, self.lyrics_list, self.music_info, self.artist_name, 
                self.album_name, self.bit_rate, self.audio_format,self.cover_label)
            self.media_player.play()  # 继续播放当前歌曲

    def previous_song(self):
        self.music_info.setTitle('')
        self.artist_name.setText('')
        self.album_name.setText('')
        self.bit_rate.setText('')
        self.audio_format.setText('')
        self.lyrics_list.clear()
        self.current_cover = None  # 新增强制清除缓存
      
        if self.cycle_mode == 1: #随机模式下的动作
            self.play_random_song()
            return
        current_item = self.playlist.currentItem()  

        if self.cycle_mode in (0, 2):  #顺序播放和单曲播放下的动作
            row = self.playlist.indexOfTopLevelItem(current_item) - 1
            if row >= 0:
                prev_item = self.playlist.topLevelItem(row)
                self.playlist.setCurrentItem(prev_item)
                
            if row == -1:
                last_item = self.playlist.topLevelItem(self.playlist.topLevelItemCount()-1)
                self.playlist.setCurrentItem(last_item)
            current_item = self.playlist.currentItem() 
            playlist_handlers.handle_playlist_double_click(self.playlist.currentItem(), self, 
                self.media_player, self.lyrics_list, self.music_info, self.artist_name, 
                self.album_name, self.bit_rate, self.audio_format,self.cover_label)
            self.media_player.play()  # 继续播放当前歌曲


    def play_random_song(self):
        import random
        count = self.playlist.topLevelItemCount()
        if count > 0:
            if not hasattr(self, 'play_history'):
                self.play_history = []
            available_indices = [i for i in range(count) if i not in self.play_history]
            if not available_indices:
                self.play_history = []
                available_indices = list(range(count))
            random_row = random.choice(available_indices)
            self.play_history.append(random_row)
            self.playlist.setCurrentItem(self.playlist.topLevelItem(random_row))
            playlist_handlers.handle_playlist_double_click(self.playlist.currentItem(), self, 
            self.media_player, self.lyrics_list, self.music_info, self.artist_name, 
            self.album_name, self.bit_rate, self.audio_format,self.cover_label)



    def toggle_cycle(self):
        # 切换播放模式
        self.cycle_mode = (self.cycle_mode + 1) % 3
        mode_names = ["顺序播放", "随机播放", "单曲循环"]
        self.cycle_button.setText(mode_names[self.cycle_mode])
        self.cycle_button.setToolTip(f"当前模式：{mode_names[self.cycle_mode]}")

    def load_cover_image(self, file_path):
        try:
            audio = File(file_path)
            cover_data = None  # 初始化cover_data
            
            if isinstance(audio, MP3):
                if audio.tags:
                    cover_data = None  # 确保变量初始化
                    for apic in audio.tags.getall('APIC'):
                        if apic.type == 3:
                            cover_data = apic.data
                            break
                    else:
                        apics = audio.tags.getall('APIC')
                        if apics:
                            cover_data = apics[0].data
                    logging.info(f'找到{len(audio.tags.getall("APIC"))}个APIC帧')
            elif isinstance(audio, FLAC):
                cover_data = next((pic.data for pic in audio.pictures if pic.type == 3), None)
            # 移除网络获取封面功能
            
            self.update_cover_image(cover_data)
            
        except Exception as e:
            logging.warning(f"封面加载失败: {str(e)}")
            self.update_cover_image(None)
        finally:
            return cover_data if cover_data else None  # 确保返回值安全

    def update_progress(self, position):
        # 更新进度条和时间显示
        duration = self.media_player.duration()
        if duration > 0:
            self.progress_slider.setValue(position)
            # 转换时间为分:秒格式
            minutes = position // 60000
            seconds = (position % 60000) // 1000
            duration_min = duration // 60000
            duration_sec = (duration % 60000) // 1000
            self.time_label.setText(f"{minutes}:{seconds:02d} / {duration_min}:{duration_sec:02d}")

    def seek_position(self, position):
        # 处理用户拖动进度条操作
        if self.media_player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
            self.media_player.pause()
        self.media_player.setPosition(position)
        if self.media_player.playbackState() != QMediaPlayer.PlaybackState.PlayingState:
            self.media_player.play()

    def handle_media_status(self, status):
        if status == QMediaPlayer.EndOfMedia:
            if self.cycle_mode == 0:  # 顺序播放
                self.next_song()
            elif self.cycle_mode == 1:  # 随机播放
                self.play_random_song()
            elif self.cycle_mode == 2:  # 单曲循环
                self.media_player.play()

    def update_play_button(self, state):
        self.play_button.setText("暂停" if state == QMediaPlayer.PlaybackState.PlayingState else "播放")

    def update_duration(self, duration):
        # 更新总时长显示
        self.progress_slider.setMaximum(duration)
        minutes = duration // 60000
        seconds = (duration % 60000) // 1000
        duration_str = f"{minutes}:{seconds:02d}"
        self.time_label.setText(f"00:00 / {duration_str}")

    def closeEvent(self, event):
        self.save_playlist()
        event.accept()

    def save_playlist(self):
        try:
            playlist_data = []
            for i in range(self.playlist.topLevelItemCount()):
                item = self.playlist.topLevelItem(i)
                file_path = item.data(6, Qt.ItemDataRole.UserRole)
                meta = item.data(6, Qt.ItemDataRole.UserRole + 1)
                playlist_data.append({
                    'file_path': str(Path(file_path).resolve()),
                    'title': meta['title'],
                    'artist': meta['artist'],
                    'album': meta['album'],
                    'duration': meta['duration'],
                    'bitrate': meta['bitrate'],
                    'format': meta['audioformat']
                })

            with open('playlist.json', 'w', encoding='utf-8') as f:
                json.dump(playlist_data, f, indent=2, ensure_ascii=False)
        except Exception as e:
            logging.error(f'保存播放列表失败: {str(e)}')

    def show_context_menu(self, pos):
        # 转换坐标到全局坐标系
        global_pos = self.playlist.viewport().mapToGlobal(pos)
        # 显示右键菜单
        self.context_menu.exec(global_pos)

    def delete_selected_items(self):
        selected_items = self.playlist.selectedItems()
        if not selected_items:
            return

        reply = QMessageBox.question(self, '确认删除', '确定要删除选中的{}项吗？'.format(len(selected_items)))
        if reply == QMessageBox.StandardButton.Yes:
            # 反向删除避免索引变化
            for item in reversed(selected_items):
                (self.playlist.invisibleRootItem() if item.parent() is None else item.parent()).removeChild(item)
            
            # 立即保存并刷新界面
            self.save_playlist()
            self.playlist.viewport().update()
            
            # 重排所有项目序号
            for index in range(self.playlist.topLevelItemCount()):
                item = self.playlist.topLevelItem(index)
                item.setText(0, str(index + 1))

    def export_selected_items(self):
        selected_items = self.playlist.selectedItems()
        if not selected_items:
            return

        path, _ = QFileDialog.getSaveFileName(self, '导出播放列表', '', 'M3U Playlist Files (*.m3u)')
        if path:
            with open(path, 'w', encoding='utf-8') as f:
                f.write('#EXTM3U\n')
                for item in selected_items:
                    file_path = os.path.normpath(item.data(6, Qt.ItemDataRole.UserRole))
                    f.write(f'{file_path}\n')

    def load_playlist(self):
        try:
            self.playlist.clear()  # 清空现有播放列表
            if Path('playlist.json').exists():
                with open('playlist.json', 'r', encoding='utf-8') as f:
                    playlist_data = json.load(f)
                
                for item_data in playlist_data:
                    file_path = Path(item_data['file_path'])
                    if file_path.exists():
                        self._add_to_playlist(str(file_path))
                    else:
                        logging.warning(f'文件不存在: {file_path}')
            # 初始化当前选中项
            if self.playlist.topLevelItemCount() > 0:
                self.playlist.setCurrentItem(self.playlist.topLevelItem(0))
        except Exception as e:
            logging.error(f'加载播放列表失败: {str(e)}')
            QMessageBox.critical(self, "加载错误", f"播放列表加载失败:\n{str(e)}")



if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())